from games import *
from board import *
from pieces import *

from math import sqrt



class State():
	
	def __init__(self,board,to_move,movesCounter):
		self.board=board
		self.to_move=to_move
		self.threatenedCells=self.board.getThreatenedCells(to_move)
		self.movesCounter=movesCounter
		
class ChessProblem(Game):
	
	def __init__(self,board,to_move, number=1):
		self.initial=State(board,to_move,0)
		self.numberOfMoves=number
	
	def inBoard(self,cell):
		if((cell[0] >7 ) or (cell[0] < 0) or (cell[1] > 7) or (cell[1] < 0) ):
				return False
		return True
		
	def actions(self, state):
		"Return a list of the allowable moves at this point."
		moves=[]

		if(state.to_move=='W'):
			pieces= state.board.getWhitePieces()
		else:
			pieces= state.board.getBlackPieces()

		for p in pieces:

			blockedTrayectory=[]

			for move in p.posible_cells():
				if(self.analizeMove(state,p,move,blockedTrayectory)):
					moves.append([p.position,move])

		return moves

	def analizeMove(self,state,piece, move,blockedTrayectory):
		
		futureCell=list(move)
		pos=list(piece.position)
		m=[]
		m.append(futureCell[0]-pos[0])
		m.append(futureCell[1]-pos[1])
		
		
		if(piece.name=='P'):
			if(state.to_move=='W' and m[0]>0):
				return False
			if(state.to_move=='B' and m[0]<0):
				return False
					
			if( m[0]!= 0 and m[1]!=0):	
				if not(state.board.thereIsOponentPiece(move,state.to_move)):
					return False
		
			if((2 in m) or (-2 in m)):
				if not(state.board.checkPawnDobleMov(pos,state.to_move)):
					return False
			
			if(state.board.cellOccuped(tuple(futureCell))):
				return False
		
		if(piece.name=='K'):
			if(tuple(futureCell) in state.threatenedCells):
				return False
		
		if(futureCell in blockedTrayectory):
			return False

		"Si hay una pieza propia en la casilla o si esta el rey"
		if(state.board.friendlyFire(futureCell,state.to_move)  or (state.board.getBlackKingPosition() == tuple(futureCell)) or (state.board.getWhiteKingPosition() == tuple(futureCell)) ):
			"""Asegura que los movimientos en la misma direccion no sean permitidos.
			El caballo es la unica excepcion"""
			if(piece.name!='N'):
				direction=[]
									
				if(m[0]==0):
					direction.append(m[0])
				else:
					direction.append(m[0]/int(sqrt(m[0]**2)))
				if(m[1]==0):
					direction.append(m[1])
				else:
					direction.append(m[1]/int(sqrt(m[1]**2)))
				
				
				while(self.inBoard(futureCell)):
					futureCell=list(futureCell)
					futureCell[0]+=direction[0]		
					futureCell[1]+=direction[1]	
					blockedTrayectory.append(futureCell)	
			
			return False				
		
		return True
					
        
	def result(self, state, move):
		"Return the state that results from making a move from a state."
		
		if(state.to_move=='W'):
			to_move='B'
		else:
			to_move='W'
		
		board=Board()
			
		
		for p in state.board.white:
			board.addWhitePiece(p)
		for p in state.board.black:
			board.addBlackPiece(p)	
		
		for p in board.white:
			if(move[1]==p.position):
				board.white.remove(p)			
			if(move[0]==p.position):
				p.position=move[1]
				
		for p in board.black:
			if(move[1]==p.position):
				board.black.remove(p)			
			if(move[0]==p.position):
				p.position=move[1]
		
		
		board.isCrowning(state.to_move)		
		
		newState=State(board,to_move,state.movesCounter+1)
			
		'''	
		print '\n', move
		board.loadBoard()
		board.printBoard()
		print '\n'	
		'''
			
			
		return newState

	def utility(self, state, player):
		"Return the value of this final state to player."
		if(state.movesCounter==self.numberOfMoves):
			return 100
		else:	
			return 0  
							
		

	def terminal_test(self, state):
		"Return True if this is a final state for the game."
		jaqueMate=True
			
		for p in state.board.black:
			if(p.name=='K'):
				for m in p.posible_cells():
					if(m not in state.threatenedCells):
						jaqueMate=False
				
				if(p.position not in state.threatenedCells):
					jaqueMate=False
	
		if(state.movesCounter>self.numberOfMoves):
			return True
	
		return jaqueMate
	
	
	def to_move(self, state):
		"Return the player whose move it is in this state."
		return state.to_move
		
	def display(self, state):
		"Print or otherwise display the state."
		print state
	
